module Data.Graph.Integration where

import Data.Graph.Slicing
import Data.Graph.Basics
import Data.Relation.SetOfPairs
import Data.Set
   
-----------------------------------------------------------------------------
-- * Integration

-- | Integrate two graphs with respect to a base graph into a
--   new graph that contains the differences of each input graph with
--   respect to the base graph. The boolean value indicates whether the
--   graphs are interference-free, i.e. whether the integration is valid. 
integrate :: Ord a => Rel a a -> Rel a a -> Rel a a -> (Rel a a,Bool)
integrate a b base
  = (m,ok)
    where
      apa = affectedPoints a base
      apb = affectedPoints b base
      aapa = a // apa
      bapb = b // apb
      basepp  = base // (preservedPoints a b base)
      m = aapa `union` bapb `union` basepp
      ok = m//apa == aapa && m//apb == bapb
      g / v = sliceBackward (singleton v) g
      g // s = sliceBackward s g

-- | Points in the first graph that are affected by changes with respect
--   to the base graph.
affectedPoints :: Ord a => Rel a a -> Rel a a -> Set a
affectedPoints x base
        = fromList [ v | v <- elems (ent x), (base/v) /= (x/v) ]
          where
            g / v = sliceBackward (singleton v) g

-- | Points in the base graph that are not affected by changes in either
--   input graph.
preservedPoints ::  Ord a => Rel a a -> Rel a a -> Rel a a -> Set a
preservedPoints x y base
        = fromList [ v | v <- elems (ent base), 
                      let  base' = base/v in base' == (x/v) && base' == (y/v)
                ]
          where
            g / v = sliceBackward (singleton v) g
            



